好不容易學會了各種單字
接下來就是把他們組在一起了
在這個單元裡,會先解釋單字和片語,然後再把段落引出來。
了解述句、運算式和區塊。
述句( statement ) 就是 句子。
運算式( expression ) 就是 片語。
為什麼分辨他們很重要?你需要知道他們回傳給你的是什麼。
var a = 3 * 6;
var b = a;
b;
JS 中的每個運算式都能夠被估算 ( evaluate ) 為單一特定的值作為結果。
3 * 6
, a
, b
都是運算式。他們都會估算當下儲存的變數值。
a = 3 * 6
, b = a
是指定運算式( assignment expressions )。
最後一行 b
自成一格,是運算式述句 ( expression statement )。
述句都有完成值。( completion values,即便那個值只是 undefined。)
就是在 Devtool,常看到的灰色 undefine,就是當下述句的完成值。
如何在程式中呼叫呢?
要用到 eval 和 ES7 的 do(..) 解決方案。(請看書)
但是 eval 別使用,ES7 還在規劃。(這就是沒有吧!?)
目前述句完成值還不是很重要,但未來可能會佔有一席之地。
大多數運算式不會有副作用。
(什麼是副作用? 真的是很疑惑,目前是以治療咳嗽,會產生頭暈的狀態看待。)
function foo(){
a = a + 1;
}
var a = 1;
foo(); // 結果:undefined,副作用:a 的值變了。
var a = 42;
a++; // 42
a; // 43
var b = 42;
b++; // 43
b; // 43
都是產生副作用,但產生的時間點不太一樣
a++
運算式回傳值 後 發生。++b
運算式回傳值 前 發生。++b
會先 ++
再回傳 b )如何想封住後發的副作用,怎麼辦?(讓兩個值相等)
可以用,述句序列逗號運算子 ( statement-series comma operator )。
var a = 42;
(a++, a); // 43
a; // 43
運算式 a++,a
,代表第二個 a 述句運算式,會在 a++ 運算式的後發副作用之後被估算。
意味著,他會回傳43。
var obj = {
a: 42
};
obj.a; // 42
delete obj.a; // true
obj.a; // undefined
delete 結果:true,副作用:移除 a。
( 內心吶喊,原來 移除 a
是副作用啊!)。
var a;
a = 42; // 42
a; // 42
a = 42
看起來不像是有副作用的運算子。
但是我們檢視 a = 42 述句的結果值,就是剛才指定的值 42。
所以將同樣的值,指定給 a 就是副作用。
var a, b, c;
a = b = c = 42;
c = 42
運算式的值 42,副作用是指定了 42 給 c。
這個結果變成看 b = 42
,再以此類推,得到 a = 42
。
在指定的部分,都是副作用。
書上有另一個藉由副作用重構程式碼的方式,請再參考吧!
相同的文字,可能會因為上下文的關係,而改變他的意思。
JavaScript 也一樣。
相同的符號,會因為上下文,有不同的用途。
主要有兩種用途。
當 {..} 是被 指定 給 某符號 的一個值。就成為物件。
var a = {
foo: bar()
};
那沒有 assign 的 {..} 呢?
就是普通的區塊,但是這在 let 區塊範疇宣告會特別有用。
若我的區塊有名字,在程式執行時,就可跳到特定區塊執行。
(有點像 goto,能不用就別用,非常少見)
foo: for (var i=0; i<4; i++){
for (var j=0; j<4; j++){
if (j == i){
continue foo;
}
if ((j * i) % 2 == 1){
continue;
}
console.log( i, j );
}
}
// 0 0 (i==j) continue foo,跳出迴圈,從 foo 再跑 i++
// 1 0 回傳 log
// 1 1 (i==j) continue foo,跳出迴圈,從 foo 再跑 i++
// 2 0 回傳 log
// 2 1 回傳 log
// 2 2 (i==j) continue foo,跳出迴圈,從 foo 再跑 i++
// 3 0 回傳 log
// 3 1 ((j * i) % 2 == 1),continue 重跑回圈 j++>。
// 3 2 回傳 log
// 3 3 (i==j) continue foo,跳出迴圈,從 foo 再跑 i++
// 4 不進入迴圈。
如果你要使用帶標籤的跳躍,請確保你有以大量的註解說明你在做什麼。
來解說之前提過的問題。
[] + {}; // "[object object]"
{} + []; // 0
+
兩邊會做 ToPrimitive 強制轉型。結果分別是 ""
和 "[object object]"
。這是字串合併的結果。{}
只是 區塊。整句可以看成 {}; +[];
,+[]
會將 String 轉成 Number,得到 0
。從 ES6 開始,新增的功能。
function foo({a,b,c}) {
console.log(a, b, c);
}
foo({
c: [1, 2, 3],
a: 42,
b: "foo"
}); // 42 "foo" [1, 2, 3]
藉由使用具名的函式引數 ( named function argument ),就可以取出物件裡特定的屬性。
下面是常見的基本語法
if (a) {
// ..
}
else if (b) {
// ..
}
else {
// ..
}
其實它實際上是這樣剖析
if (a) {
// ..
}
else {
if (b) {
// ..
}
else {
// ..
}
}
if 與 else 述句接附的區塊若只含單一個述句,就能夠省略他們周圍的
{}
。
if (a) doSomething(b);
// 等同於
if (a) { doSomething(b); }
但有些風格指南會要求一定要加上 {}。
如果你也慣用 else if 的話,你也就間接打破風格了喔!啾咪。
今天就是了解
{}
下一章就是
明~天~見~